from sqlmodel import select
from sqlalchemy.orm import joinedload, selectinload
from app import  models,crud
from typing import Optional
from app.core.security import get_password_hash
from fastapi import status
from .base import BaseService
from app.utils import generate_verification_code,send_sms
from datetime import datetime,timedelta
import logging

class UsersService(BaseService):    

    async def delete_user(self, id: str) -> models.UserPublicResponse:

        user = await crud.User(self.db).find(id)
        if not user:
            return  models.UserPublicResponse(code=status.HTTP_404_NOT_FOUND, msg="User not found",data=None)
        if user == self.current_user :
            return  models.UserPublicResponse(code=status.HTTP_403_FORBIDDEN, msg="Super users are not allowed to delete themselves",data=None)
            
        return await self.delete_me(id)            
    
    async def delete_me(self, id: str) ->  models.UserPublicResponse:
             
        res =  await crud.User(self.db).delete(id)   
        return models.UserPublicResponse(code=0, msg="用户删除成功",data=res)

    

    async def read_users_by_id(self,  user_id: int ) -> models.UserPublicResponse:
        
        user = await crud.User(self.db).find(user_id)

        if user == self.current_user:
            return models.UserPublicResponse(code=0,msg="读取成功",data=user) 
        if not self.current_user.is_superuser:
            return models.UserPublicResponse(
                code=403,
                msg="The user doesn't have enough privileges",
                data=None
            )
        if not user:
            return models.UserPublicResponse(
                code=404,
                msg="User not found",
                data=None
            )          
        return models.UserPublicResponse(code=0,msg="读取成功",data=user) 
        

    
    async def read_users(self,  skip: int = 0, limit: int = 100) -> Optional[models.User]:
        stmt = (
            select(models.User)
            .offset(skip).limit(limit)
        )        
        return  self.db.exec(stmt).all()

    async def get_user_with_item(self, id: int) -> Optional[models.User]:
        stmt = (
            select(models.User)
            .where(models.User.id == id)
            .options(
                joinedload(models.User.items, innerjoin=False).selectinload(
                    models.Item
                )
            )
        )
        result = self.db.exec(stmt)
        return result.scalar_one_or_none()

    async def create_user(self, payload: models.UserCreate) -> models.UserPublicResponse:
        
        user = await crud.User(self.db).find_by({"email":payload.email})
        
        if user:
            return models.UserPublicResponse(
                code=status.HTTP_400_BAD_REQUEST,
                msg="The user with this email already exists in the system.",
                data=None
            )        
                    
        user_create = models.UserCreate.model_validate(payload)
        res = await crud.User(db=self.db).create(user_create)
        return models.UserPublicResponse(
                code=0,
                msg="创建成功",
                data=res
            )
    
    async def update_password(
        self,payload: models.UpdatePassword
    ) -> models.UserPublicResponse:
        
        self.current_user.hashed_password =  get_password_hash(payload.new_password) 
        self.db.add(self.current_user)
        self.db.commit()
        return models.UserPublicResponse(data=self.current_user,msg="更新成功",code=0)

    async def update_me(
        self,  payload: models.UserProfileUpdateMe
    ) -> models.UserPublicResponse:
        return await self.update_user_by_id(self.current_user.id,payload)
    
    async def update_user_by_id(
        self,user_id:int,  payload: models.UserProfileUpdateMe
    ) -> models.UserPublicResponse:
        
        db_user = await crud.User(self.db).find(user_id)
        if not db_user:
            return models.UserPublicResponse(code=status.HTTP_404_NOT_FOUND,
                msg="The user with this id does not exist in the system",data=None)
                
        
        user_data = payload.model_dump(exclude_unset=True)        
        db_user.sqlmodel_update(user_data)
        self.db.add(db_user)
        self.db.commit()
        self.db.refresh(db_user)
        return  models.UserPublicResponse(code=0,
                msg="更新成功",data=db_user)
        
    async def request_verification_code(
        self,payload:models.PhoneVerificationCodeRequest
    ) -> models.PhoneVerificationCodeResponse:
        
            # 生成验证码
        verification_code = '123456' #generate_verification_code()

        # 尝试发送验证码
        if not send_sms(payload.phone, verification_code):
            return  models.PhoneVerificationCodeResponse(code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                msg="验证码发送失败",data=None)
        # 存储验证码信息
        expires_at = datetime.now() + timedelta(minutes=1)
        new_verification = models.PhoneVerification(
            phone=payload.phone,
            code=verification_code,
            expiresAt=expires_at,
            purpose=payload.purpose
        )
        self.db.add(new_verification)
        self.db.commit()
        self.db.refresh(new_verification)
        return  models.PhoneVerificationCodeResponse(code=0,
                msg="成功",data=None)

    async def register_user_by_phone(
        self,register_in:models.PhoneRegisterRequest
    ) -> models.PhoneRegisterResponse:

        # 查询数据库中存储的验证码
        stmt = (
            select(models.PhoneVerification)
            .where(
                models.PhoneVerification.phone == register_in.phone,
                models.PhoneVerification.code == register_in.verification_code,
                models.PhoneVerification.expiresAt > datetime.now(),
                models.PhoneVerification.purpose == models.VerificationPurpose.REGISTER,
                models.PhoneVerification.verifiedTime == None
            )
        )
        verification = self.db.exec(stmt).first()
        if not verification:
            return  models.PhoneRegisterResponse(code=status.HTTP_400_BAD_REQUEST,
                msg="非法验证码",data=None)     
        user = await crud.User(self.db).find_by({"account":register_in.phone,"accountType":models.AccountType.PHONE})
        
        if user:
            return models.PhoneRegisterResponse(
                code=status.HTTP_400_BAD_REQUEST,
                msg="这个手机的用户已经存在于系统，注册失败。",
                data=None
            )        
        # 哈希密码并创建用户
        hashed_password = get_password_hash(register_in.password)
        new_user = models.User(
            account=register_in.phone,
            accountType=models.AccountType.PHONE,
            hashed_password=str(hashed_password),       
                #  给一个默认头像
            headPortrait='https://i.pinimg.com/736x/37/f8/2d/37f82d5a37d07f1abb4f31f2daeacb9f.jpg',
            nickName='手机用户',
            status=models.UserStatus.ENABLED           
        )
        self.db.add(new_user)
        self.db.commit()
        self.db.refresh(new_user) 
        
        # 更新验证码状态
        verification.verifiedTime = datetime.now()
        self.db.add(verification)
        self.db.commit()

        return models.PhoneRegisterResponse(code=0,
                msg="注册成功",data=None)     
        
    async def find_user_by(self,fileter_str:dict)->models.user:
        return await crud.User(self.db).find_by(kwargs=fileter_str)        

    async def find_user_with_auth_by(self, filter_dict: dict):
        user_conditions = [getattr(models.User, key) == value for key, value in filter_dict.items()]
        statement = (
            select(models.User)
            .where(
                *user_conditions
            )
        )
        
        # 方法1：直接打印 SQL 语句
        # print("Generated SQL:", statement.compile(compile_kwargs={"literal_binds": True}))
        
        result = self.db.execute(statement)
        return result.scalars().first()    
        
    async def get_user_me_authinfo(self, filter_dict: dict):
        _conditions = [getattr(models.UserAuth, key) == value for key, value in filter_dict.items()]
        statement = (
            select(models.UserAuth)
            .where(
                *_conditions
            )
        )
        
           
        result = self.db.exec(statement)
        auth_list = result.all()
        return models.UserAuthResponse(code=0, msg="获取成功", data=auth_list)        

    async def get_university_by_name(self,name:str):
        stmt = (
            select(models.University)
            .where(models.University.name.like(f"%{name}%"))
        )
        result = self.db.exec(stmt)
        universities = result.all()
        return models.UniversitysPublic(
            code=0,
            msg="查询成功",
            data=universities
        )